package com.example.finaltool.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.finaltool.consts.Table;
import com.example.finaltool.consts.range.RangeType;
import com.example.finaltool.mapper.*;
import com.example.finaltool.model.RangeCheck;
import com.example.finaltool.model.RangeQuery;
import com.example.finaltool.model.Result;
import com.example.finaltool.model.db.info.*;
import com.example.finaltool.model.DepInfo;
import com.example.finaltool.utils.PrintUtils;
import com.example.finaltool.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author dengbw
 * @date 2021/8/11 3:00 下午
 */
@Slf4j
@Service
public class InfoService {
    InfoConsultingMapper consultingMapper;
    DingCommonService dingCommonService;
    InfoGuidanceMapper guidanceMapper;
    InfoHuinongMapper huinongMapper;
    InfoNewsMapper newsMapper;
    InfoOpenMapper openMapper;
    InfoRuralMapper ruralMapper;

    InfoConsultingRangeMapper rangeMapper;
    InfoMapper infoMapper;

    @Autowired
    public InfoService(InfoConsultingMapper consultingMapper,
                       InfoGuidanceMapper guidanceMapper,
                       InfoHuinongMapper huinongMapper,
                       InfoNewsMapper newsMapper,
                       InfoOpenMapper openMapper,
                       InfoRuralMapper ruralMapper,
                       DingCommonService dingCommonService,
                       InfoConsultingRangeMapper rangeMapper,
                       InfoMapper infoMapper) {
        this.consultingMapper = consultingMapper;
        this.guidanceMapper = guidanceMapper;
        this.huinongMapper = huinongMapper;
        this.newsMapper = newsMapper;
        this.openMapper = openMapper;
        this.ruralMapper = ruralMapper;
        this.dingCommonService = dingCommonService;
        this.rangeMapper = rangeMapper;
        this.infoMapper = infoMapper;
    }

    @Transactional(rollbackFor = Exception.class)
    public Result<List<String>> copyInfo(String corpId, String appKey, String appSecret) {
        PrintUtils.separator();
        DepInfo info = dingCommonService.fetchDepInfo(appKey, appSecret);
        log.info("资讯开始复制");
        LocalDateTime startTime = LocalDateTime.now();
        List<RangeCheck> existList = rangeMapper.getExist(corpId);
        Set<RangeCheck> existSet = ConcurrentHashMap.newKeySet(existList.size());
        existSet.addAll(existList);
        List<String> result = new ArrayList<>();
        result.add(copyConsult(corpId, info.cunIds(), existSet));
        result.add(copyGuidance(corpId, info.cunIds(), existSet));
        result.add(copyHuinong(corpId, info.cunIds(), existSet));
        result.add(copyNews(corpId, info.cunIds(), existSet));
        result.add(copyOpen(corpId, info.cunIds(), existSet));
        result.add(copyRural(corpId, info.cunIds(), existSet));
        log.info("资讯复制结束, 用时" + TimeUtils.duration(startTime));
        return Result.success(result);
    }

    private String copyConsult(String corpId, List<Long> infos, Set<RangeCheck> existSet) {
        List<Long> minus = new ArrayList<>(infos);
        QueryWrapper<Consulting> wrapper = new QueryWrapper<>();
        wrapper.eq("tenant_id", corpId).isNotNull("sub_tenant_id");
        List<String> a = consultingMapper.getExistSubIds(corpId);
        List<Long> existSub = a.stream().map(Long::valueOf).collect(Collectors.toList());
        minus.removeAll(existSub);
        List<Consulting> existList = consultingMapper.selectList(wrapper);
        if (!existList.isEmpty()) {
            existList.stream().parallel().forEach(c -> minus.forEach(subs -> {
                c.setSubTenantId(String.valueOf(subs));
                c.setId(null);
                consultingMapper.insert(c);
            }));
            // 更新发布范围
            List<Range> consultRange = infoMapper.getRange(Table.INFO_CONSULTING, RangeType.get(Table.INFO_CONSULTING), corpId);
            consultRange.stream().parallel().forEach(r -> {
                RangeCheck check = new RangeCheck(r);
                if (!existSet.contains(check)) {
                    rangeMapper.insert(r);
                    existSet.add(check);
                }
            });
        }
        String result = "已将" + existList.size() + "条党建天地复制到其余" + minus.size() + "个村中";
        log.info(result);
        return result;
    }

    private String copyGuidance(String corpId, List<Long> infos, Set<RangeCheck> existSet) {
        List<Long> minus = new ArrayList<>(infos);
        QueryWrapper<Guidance> wrapper = new QueryWrapper<>();
        wrapper.eq("tenant_id", corpId).isNotNull("sub_tenant_id");
        List<Long> existSub = guidanceMapper.getExistSubIds(corpId);
        minus.removeAll(existSub);
        List<Guidance> existList = guidanceMapper.selectList(wrapper);
        if (!existList.isEmpty()) {
            existList.stream().parallel().forEach(c -> minus.forEach(subs -> {
                c.setSubTenantId(subs);
                c.setId(null);
                guidanceMapper.insert(c);
            }));
            // 更新发布范围
            List<RangeQuery> consultRange = infoMapper.getRangeQuery(Table.INFO_GUIDANCE, RangeType.get(Table.INFO_GUIDANCE), corpId);
            consultRange.stream().parallel().forEach(r -> {
                RangeCheck check = new RangeCheck(r);
                if (!existSet.contains(check)) {
                    Range range = new Range(r);
                    rangeMapper.insert(range);
                    existSet.add(check);
                }
            });
        }
        String result = "已将" + existList.size() + "条农事指导复制到其余" + minus.size() + "个村中";
        log.info(result);
        return result;
    }

    private String copyHuinong(String corpId, List<Long> infos, Set<RangeCheck> existSet) {
        List<Long> minus = new ArrayList<>(infos);
        QueryWrapper<Huinong> wrapper = new QueryWrapper<>();
        wrapper.eq("tenant_id", corpId).isNotNull("sub_tenant_id");
        List<Long> existSub = huinongMapper.getExistSubIds(corpId);
        minus.removeAll(existSub);
        List<Huinong> existList = huinongMapper.selectList(wrapper);
        if (!existList.isEmpty()) {
            existList.stream().parallel().forEach(c -> minus.forEach(subs -> {
                c.setSubTenantId(subs);
                c.setId(null);
                huinongMapper.insert(c);
            }));
            // 更新发布范围
            List<RangeQuery> consultRange = infoMapper.getRangeQuery(Table.INFO_HUINONG, RangeType.get(Table.INFO_HUINONG), corpId);
            consultRange.stream().parallel().forEach(r -> {
                RangeCheck check = new RangeCheck(r);
                if (!existSet.contains(check)) {
                    Range range = new Range(r);
                    rangeMapper.insert(range);
                    existSet.add(check);
                }
            });
        }
        String result = "已将" + existList.size() + "条惠农政策复制到其余" + minus.size() + "个村中";
        log.info(result);
        return result;
    }

    private String copyNews(String corpId, List<Long> infos, Set<RangeCheck> existSet) {
        List<Long> minus = new ArrayList<>(infos);
        QueryWrapper<News> wrapper = new QueryWrapper<>();
        wrapper.eq("tenant_id", corpId).isNotNull("sub_tenant_id");
        List<Long> existSub = newsMapper.getExistSubIds(corpId);
        minus.removeAll(existSub);
        List<News> existList = newsMapper.selectList(wrapper);
        if (!existList.isEmpty()) {
            existList.stream().parallel().forEach(c -> minus.forEach(subs -> {
                c.setSubTenantId(subs);
                c.setId(null);
                newsMapper.insert(c);
            }));
            // 更新发布范围
            List<RangeQuery> consultRange = infoMapper.getRangeQuery(Table.INFO_NEWS, RangeType.get(Table.INFO_NEWS), corpId);
            consultRange.stream().parallel().forEach(r -> {
                RangeCheck check = new RangeCheck(r);
                if (!existSet.contains(check)) {
                    Range range = new Range(r);
                    rangeMapper.insert(range);
                    existSet.add(check);
                }
            });
        }
        String result = "已将" + existList.size() + "条乡村快讯复制到其余" + minus.size() + "个村中";
        log.info(result);
        return result;
    }

    private String copyOpen(String corpId, List<Long> infos, Set<RangeCheck> existSet) {
        List<Long> minus = new ArrayList<>(infos);
        QueryWrapper<Open> wrapper = new QueryWrapper<>();
        wrapper.eq("tenant_id", corpId).isNotNull("sub_tenant_id");
        List<Long> existSub = openMapper.getExistSubIds(corpId);
        minus.removeAll(existSub);
        List<Open> existList = openMapper.selectList(wrapper);
        if (!existList.isEmpty()) {
            existList.stream().parallel().forEach(c -> minus.forEach(subs -> {
                c.setSubTenantId(subs);
                c.setId(null);
                openMapper.insert(c);
            }));
            // 更新发布范围
            List<RangeQuery> consultRange = infoMapper.getRangeQuery(Table.INFO_OPEN, RangeType.get(Table.INFO_OPEN), corpId);
            consultRange.stream().parallel().forEach(r -> {
                RangeCheck check = new RangeCheck(r);
                if (!existSet.contains(check)) {
                    Range range = new Range(r);
                    rangeMapper.insert(range);
                    existSet.add(check);
                }
            });
        }
        String result = "已将" + existList.size() + "条三务公开复制到其余" + minus.size() + "个村中";
        log.info(result);
        return result;
    }

    private String copyRural(String corpId, List<Long> infos, Set<RangeCheck> existSet) {
        List<Long> minus = new ArrayList<>(infos);
        QueryWrapper<Rural> wrapper = new QueryWrapper<>();
        wrapper.eq("tenant_id", corpId).isNotNull("sub_tenant_id");
        List<Long> existSub = ruralMapper.getExistSubIds(corpId);
        minus.removeAll(existSub);
        List<Rural> existList = ruralMapper.selectList(wrapper);
        if (!existList.isEmpty()) {
            existList.stream().parallel().forEach(c -> minus.forEach(subs -> {
                c.setSubTenantId(subs);
                c.setId(null);
                ruralMapper.insert(c);
            }));
            // 更新发布范围
            List<RangeQuery> consultRange = infoMapper.getRangeQuery(Table.INFO_RURAL, RangeType.get(Table.INFO_RURAL), corpId);
            consultRange.stream().parallel().forEach(r -> {
                RangeCheck check = new RangeCheck(r);
                if (!existSet.contains(check)) {
                    Range range = new Range(r);
                    rangeMapper.insert(range);
                    existSet.add(check);
                }
            });
        }
        String result = "已将" + existList.size() + "条美丽乡村复制到其余" + minus.size() + "个村中";
        log.info(result);
        return result;
    }

    public Result<Boolean> fillSubIds(String corpId, String appKey, String appSecret) {
        PrintUtils.separator();
        DepInfo info = dingCommonService.fetchDepInfo(appKey, appSecret);
        PrintUtils.stepStart("补全subId");
        LocalDateTime start = LocalDateTime.now();
        info.getCunDepInfoList().forEach(c -> infoMapper.fillSub(corpId, c.getCunName(), c.getCunDepId()));
        PrintUtils.stepFinish("补全subId, 用时" + TimeUtils.duration(start));
        return Result.success();
    }
}
